/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.web.frontendproject.metadata;

import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.service.MetadataService;
import com.inspur.edp.web.appconfig.api.entity.GspAppConfig;
import com.inspur.edp.web.appconfig.core.service.GspAppConfigService;
import com.inspur.edp.web.common.entity.TerminalType;
import com.inspur.edp.web.common.io.FileUtility;
import com.inspur.edp.web.common.utility.RandomUtility;
import com.inspur.edp.web.formmetadata.resolver.ResolveFormMetadataList;
import com.inspur.edp.web.frontendproject.entity.ChosenFormList;
import com.inspur.edp.web.frontendproject.formdynamic.FormDynamicTagGetter;
import com.inspur.edp.web.frontendproject.pageflow.PageFlowMetadataManager;
import com.inspur.edp.web.pageflow.metadata.entity.Page;
import com.inspur.edp.web.pageflow.metadata.entity.PageFlowMetadataEntity;
import com.inspur.edp.web.pageflow.metadata.service.PageFlowMetadataUpdateService;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;

/**
 * 表单元数据管理
 *
 * @author guozhiqi
 */
public class FormMetadataManager {

    /**
     * 检查表单元数据是否存在
     */
    public static boolean checkFormMetadataExists(String projectPath, TerminalType terminalType, ChosenFormList buildFormList, boolean isJieXiForm, boolean saveRouteJson) {
        return FormMetadataManager.getFormMetadataList(projectPath, terminalType, buildFormList, saveRouteJson).isNotEmpty();
    }


    /**
     * 获取表单元数据列表  默认会保存页面流文件内容至route.json
     */
    public static ResolveFormMetadataList getFormMetadataList(String projectPath, TerminalType terminalType, ChosenFormList buildFormList) {
        return getFormMetadataList(projectPath, terminalType, buildFormList, true);
    }

    /**
     * 解析表单元数据列表
     * 为了支持元数据变更检测  ，所以增加参数saveRouteJson，布进行route.json 文件保存动作
     *
     * @param projectPath
     * @param terminalType
     * @param buildFormList
     * @param saveRouteJson
     * @return
     */
    public static ResolveFormMetadataList getFormMetadataList(String projectPath, TerminalType terminalType, ChosenFormList buildFormList, boolean saveRouteJson) {
        // 1.从工程中读取工程配置文件
        GspAppConfig appConfigurationInfo = GspAppConfigService.getCurrent().getOrCreateAppConfig(projectPath);

        // 2.获取路由元数据中内容
        ResolveFormMetadataList formMetadataList = ResolveFormMetadataList.getNewInstance();
        PageFlowMetadataEntity pageFlowMetadataEntity;

        // 如果为空那么设置其为默认值
        if (buildFormList == null) {
            buildFormList = ChosenFormList.getNewInstance();
        }

        if (buildFormList.isNotEmpty()) {
            String id = RandomUtility.newGuid();
            PageFlowMetadataEntity fullPageFlowEntity = PageFlowMetadataUpdateService.getInstance().createPageFlowMetadataEntity(id, projectPath, terminalType.getFormMetadataSuffix());
            pageFlowMetadataEntity = PageFlowMetadataManager.filterPageFlowPages(fullPageFlowEntity, buildFormList);
        } else {
            pageFlowMetadataEntity = PageFlowMetadataManager.getPageFlowEntityList(projectPath, appConfigurationInfo, terminalType);

            // 页面流不存在、页面流中没有表单时返回空列表
            if (pageFlowMetadataEntity == null || pageFlowMetadataEntity.hasEmptyPage()) {
                return formMetadataList;
            }
        }

        // 3.将路由元数据内容暂存到指定目录下
        if (saveRouteJson) {
            PageFlowMetadataManager.saveRouteMetadata(pageFlowMetadataEntity, projectPath, terminalType);
        }

        // 4.获取待编译表单元数据集合
        formMetadataList = getFormMetadataList(pageFlowMetadataEntity.getPages(), projectPath);

        return formMetadataList;
    }


    /**
     * 根据页面流文件信息获取对应的表单元数据信息
     *
     * @param pages
     * @return
     */
    private static ResolveFormMetadataList getFormMetadataList(Page[] pages, String projectPath) {
        ResolveFormMetadataList matchedFormMetadataList = ResolveFormMetadataList.getNewInstance();

        MetadataService metadataService = SpringBeanUtils.getBean(MetadataService.class);
        for (Page page : pages) {
            String pageRelativePath = modifyPageRelativePath(page.getRelativePath(), projectPath);

            // 如果对应的表单元数据路径为绝对路径  那么需要进行调整
            if (FileUtility.isAbsolute(pageRelativePath)) {
                throw new RuntimeException("页面流文件(后缀为.pf)中包含绝对路径，依赖于单个环境路径配置，请调整为相对路径。具体操作：打开页面流文件，通过将表单从页面流中先移除再添加的方式，自动进行调整。  对应表单元数据为：" + page.getName() + "，当前绝对路径为：" + page.getRelativePath());
            }
            // 增加表单元数据的存在检测
            if (!metadataService.isMetadataExist(pageRelativePath, page.getFileName())) {
                throw new RuntimeException("页面流文件(后缀为.pf)中配置表单元数据路径不正确，请移除。对应表单元数据code：" + page.getCode() + ",name: " + page.getName());
            }
            GspMetadata currentRouteMetadata = metadataService.loadMetadata(page.getFileName(), pageRelativePath);

            // 读取元数据得解析状态标识
            boolean dynamicFormTag = FormDynamicTagGetter.getDynamicFormTagWithGspMetadata(currentRouteMetadata);

            matchedFormMetadataList.add(currentRouteMetadata, page.isForceDynamicForm(), dynamicFormTag);
        }


        return matchedFormMetadataList;
    }

    /**
     * 修正页面相对路径 避免由于绝对路径问题导致生成异常
     *
     * @param relativePath
     * @param projectPath
     * @return
     */
    private static String modifyPageRelativePath(String relativePath, String projectPath) {
        String inDependentRelativePath = FileUtility.getPlatformIndependentPath(relativePath);
        String inDependentProjectPath = FileUtility.getPlatformIndependentPath(projectPath);
        // 如果包含工程路径
        if (inDependentRelativePath.contains(inDependentProjectPath)) {
            String tempRelativePath = inDependentRelativePath.substring(inDependentRelativePath.lastIndexOf(inDependentProjectPath));
            return tempRelativePath;
        }
        return inDependentRelativePath;
    }
}
